package com.ibm.jdg2e.editor.jfacetext.sqleditor;
/*
 * "The Java Developer's Guide to Eclipse"
 *   by D'Anjou, Fairbrother, Kehn, Kellerman, McCarthy
 * 
 * (C) Copyright International Business Machines Corporation, 2003, 2004. 
 * All Rights Reserved.
 * 
 * Code or samples provided herein are provided without warranty of any kind.
 */
import java.util.ResourceBundle;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.jface.text.source.projection.ProjectionSupport;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.ITextEditorHelpContextIds;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.ui.ide.IDEActionFactory;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.AddTaskAction;
import org.eclipse.ui.texteditor.DefaultRangeIndicator;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.ResourceAction;
import org.eclipse.ui.texteditor.TextEditorAction;
import org.eclipse.ui.texteditor.TextOperationAction;

import com.ibm.jdg2e.editor.jfacetext.sqleditor.sql.SQLCodeScanner;

/**
 * This class is responsible for configuring the SQL editor.
 *  
 */
public class SQLEditor extends AbstractDecoratedTextEditor {
  private class DefineFoldingRegionAction
      extends
        TextEditorAction {

    public DefineFoldingRegionAction(ResourceBundle bundle,
        String prefix, ITextEditor editor) {
      super(bundle, prefix, editor);
    }

    private IAnnotationModel getAnnotationModel(
        ITextEditor editor) {
      return (IAnnotationModel) editor
          .getAdapter(ProjectionAnnotationModel.class);
    }

    /*
     * @see org.eclipse.jface.action.Action#run()
     */
    public void run() {
      ITextEditor editor = getTextEditor();
      ISelection selection = editor.getSelectionProvider()
          .getSelection();
      if (selection instanceof ITextSelection) {
        ITextSelection textSelection = (ITextSelection) selection;
        if (!textSelection.isEmpty()) {
          IAnnotationModel model = getAnnotationModel(editor);
          if (model != null) {

            int start = textSelection.getStartLine();
            int end = textSelection.getEndLine();

            try {
              IDocument document = editor.getDocumentProvider()
                  .getDocument(editor.getEditorInput());
              int offset = document.getLineOffset(start);
              int endOffset = document.getLineOffset(end + 1);
              Position position = new Position(offset, endOffset
                  - offset);
              model.addAnnotation(new ProjectionAnnotation(),
                  position);
            } catch (BadLocationException x) {
              // ignore
            }
          }
        }
      }
    }
  }

  private static SQLCodeScanner fSQLCodeScanner;
  private ProjectionSupport fProjectionSupport;
  
  /**
   * Constructor for SQLEditor. Intialization takes place in the constructor of
   * SQLEditor using setDocumentProvider and setRangeIndicator.
   */
  public SQLEditor() {
    super();
    fSQLCodeScanner = new SQLCodeScanner();
    setRangeIndicator(new DefaultRangeIndicator());
  }
  /*
   * (non-Javadoc) Method declared on AbstractTextEditor
   */
  protected void initializeEditor() {
    super.initializeEditor();
    setSourceViewerConfiguration(new SQLEditorSourceViewerConfiguration());
  }
  /**
   * Clean up the font colors used in the syntax hilighting
   *  
   */
  public void disposeColorProvider() {
    SQLEditorPlugin.getDefault().disposeColorProvider();
    super.dispose();
  }

  /**
   * Method to install the editor actions.
   * 
   * <p>Changes required in V 2.1. Shortcut keys on global actions must be
   * explicitly set. Content Assist and Context Information Shortcut keys must
   * be set to the key defintion ID's.
   * 
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions()    
   */
  protected void createActions() {
    // Added in 2.1, global action revert, undo etc. are otherwise not
    // enabled
    super.createActions();
    // Above is new line reqired in 2.1 to enable undo, redo, revert actions

    ResourceBundle bundle = SQLEditorPlugin.getDefault()
        .getResourceBundle();
    IAction a = new TextOperationAction(bundle,
        "ContentAssistProposal.", this,
        ISourceViewer.CONTENTASSIST_PROPOSALS);

    // Added this call for 2.1 changes
    // New to 2.1 - CTRL+Space key doesn't work without making this call
    a.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
    setAction("ContentAssistProposal", a);

    a = new TextOperationAction(bundle, "ContentAssistTip.",
        this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION);

    //	Added this call for 2.1 changes
    a.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
    setAction("ContentAssistTip", a);

    a = new TextOperationAction(bundle,
        "ContentFormatProposal.", this, ISourceViewer.FORMAT);
    setAction("ContentFormatProposal", a);

    // Add the task action to the Edit pulldown menu (bookmark action is
    // 'free')
    ResourceAction ra = new AddTaskAction(bundle, "AddTask.",
        this);
    ra.setHelpContextId(ITextEditorHelpContextIds.ADD_TASK_ACTION);
    ra.setActionDefinitionId(ITextEditorActionDefinitionIds.ADD_TASK);
    setAction(IDEActionFactory.ADD_TASK.getId(), ra);

    //Add action to define the marked area as a folding area
    a = new DefineFoldingRegionAction(bundle,
        "DefineFoldingRegion.", this); //$NON-NLS-1$
    setAction("DefineFoldingRegion", a);

  }

  /**
   * @see AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
   */
  public void editorContextMenuAboutToShow(IMenuManager menu) {
    super.editorContextMenuAboutToShow(menu);
    addAction(menu, "ContentAssistProposal");
    addAction(menu, "ContentAssistTip");
    addAction(menu, "ContentFormatProposal");
    addAction(menu, "DefineFoldingRegion");

  }

  /**
   * Getter method that returns a SQL Code Scanner.
   * 
   * @return SQLCodeScanner
   */
  public static SQLCodeScanner getSQLCodeScanner() {
    return fSQLCodeScanner;
  }
  
  /*
   * @see org.eclipse.ui.texteditor.ExtendedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite,
   *      org.eclipse.jface.text.source.IVerticalRuler, int)
   */
  protected ISourceViewer createSourceViewer(Composite parent,
      IVerticalRuler ruler, int styles) {

    fAnnotationAccess = createAnnotationAccess();
    fOverviewRuler = createOverviewRuler(getSharedColors());

    ISourceViewer viewer = new ProjectionViewer(parent, ruler,
        getOverviewRuler(), isOverviewRulerVisible(), styles);
    // ensure decoration support has been created and configured.
    getSourceViewerDecorationSupport(viewer);

    return viewer;
  }

  /*
   * @see org.eclipse.ui.texteditor.ExtendedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite)
   */
  public void createPartControl(Composite parent) {
    super.createPartControl(parent);
    ProjectionViewer viewer = (ProjectionViewer) getSourceViewer();
    fProjectionSupport = new ProjectionSupport(viewer,
        getAnnotationAccess(), getSharedColors());
    fProjectionSupport
        .addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error");
    fProjectionSupport
        .addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning");
    fProjectionSupport.install();
    viewer.doOperation(ProjectionViewer.TOGGLE);
  }
  /*
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#adjustHighlightRange(int,
   *      int)
   */
  protected void adjustHighlightRange(int offset, int length) {
    ISourceViewer viewer = getSourceViewer();
    if (viewer instanceof ITextViewerExtension5) {
      ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
      extension.exposeModelRange(new Region(offset, length));
    }
  }

  public Object getAdapter(Class required) {

    if (fProjectionSupport != null) {
      Object adapter = fProjectionSupport.getAdapter(
          getSourceViewer(), required);
      if (adapter != null)
        return adapter;
    }

    return super.getAdapter(required);
  }
  
  /*
   * (non-Javadoc)
   * 
   * @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite,
   *      org.eclipse.ui.IEditorInput)
   * Creating the TextFileDocument provider here explicitily.  The Framework
   * will do this implicitly. 
   */
  public void init(IEditorSite site, IEditorInput input)
      throws PartInitException {
    setDocumentProvider(new TextFileDocumentProvider());
    super.init(site, input);
  }
}